<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 函数嵌套
    // 1. 外层函数在执行过程中,又调用了内层函数 -> 如果内层函数不执行完外层函数也不会结束
    // 2. 内层函数既可以引用自身作用域中的变量和方法,也可以使用父作用域的变量和方法

    // function fn() {
    //     var a = 10;
    //     console.log(a); // 10

    //     function func() {
    //         a++;
    //         console.log(a); // 11
    //         return a;
    //     }
    //     return func(); // 11
    // }

    // var res = fn();
    // console.log(res); // 11



    // 闭包:
    // 闭包是指 有权访问另一个函数作用域中的变量 的函数。
    // 简单的来说  就是 一个函数在执行过程中 返回另一个函数/对象 (引用类型   一般都是函数),另一个函数又引用外层函数中的变量

    // 闭包的实现步骤
    // 1. 在函数内容部, 返回另一个函数或多个函数(数组, 对象中)
    // 2. 返回的函数中,使用了外层函数中的局部作用域变量
    // 3. 在函数的外部, 有变量来引用返回的一个函数或多个函数

    // 闭包的优缺点
    // 优点: 1. 可以减少全局变量的使用  2.可以在函数外部访问函数内部的数据    3. 可以长时间存储数据
    // 缺点: 1. 可以在函数外部访问函数内部的数据 => 数据不安全  2. 外层函数中的局部变量或方法一直被内部引用 -> 得到不释放 -> 占内存 3. 如果页面中闭包使用过多 会导致内存泄露 



    /* function fn() {
        var a = 10; // 11  12

        function func() {
            a++;
            return a;
        }
        return func;
    } */


    /*  function fn() {
         var a = 10; // 11  12
 
         return function () {
             a++;
             return a;
         }
     }
 
     var res = fn(); // 每次调用fn => 返回一个函数func(函数内部创建) => 赋值给res(浅复制)
     console.log(res);
 
     var result = res();
     console.log(result);
 
     var result = res();
     console.log(result);
 
 
     var res = fn(); // 每次调用fn => 返回一个函数func(函数内部创建) => 赋值给res(浅复制)
     console.log(res);
 
     var result = res();
     console.log(result);
 
     var result = res();
     console.log(result); */


    function fn() {
        var a = 0;
        return {
            add: function () {
                a++;
                return a;
            },
            reduce: function () {
                a--;
                return a;
            },
            get: function () {
                return a;
            },
            set: function (val) {
                a = val;
            }
        }
    }

    var obj = fn();
    console.log(obj);

    obj.add();
    obj.add();
    obj.add();
    obj.add();
    obj.add();
    console.log(obj.get());

    obj.reduce();
    obj.reduce();
    obj.reduce();
    obj.reduce();
    console.log(obj.get());

    obj.set(100);
    console.log(obj.get());

    // obj = null;

</script>

</html>